/**
 * 
 */
package org.vsg.stock.extension.service.impl;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.vsg.common.exceptions.service.ServiceException;
import org.vsg.stock.basic.StockHelper;
import org.vsg.stock.basic.domain.StockCategory;
import org.vsg.stock.basic.domain.StockDailyLine;
import org.vsg.stock.basic.domain.StockInfo;
import org.vsg.stock.basic.persistence.StockCategoryDao;
import org.vsg.stock.basic.persistence.StockDailyLineDao;
import org.vsg.stock.basic.persistence.StockInfoDao;
import org.vsg.stock.extension.processor.FilterProcessorManager;
import org.vsg.stock.extension.service.StockAnalysisService;
import org.vsg.stock.extension.service.StockHistoryService;
import org.vsg.stock.extension.vo.AttentionBlock;
import org.vsg.stock.extension.vo.CloserPatternStock;
import org.vsg.stock.extension.vo.HistoryPatternStock;
import org.vsg.stock.extension.vo.LinkageCateShownSequenceVO;
import org.vsg.stock.extension.vo.LinkageCateStockVO;
import org.vsg.stock.extension.vo.LinkageStock;
import org.vsg.stock.extension.vo.LinkageStockGroup;
import org.vsg.stock.extension.vo.LinkageStockGroupCounterVO;
import org.vsg.stock.extension.vo.LinkageStockGroupCounterView;
import org.vsg.stock.extension.vo.LinkageStocksItemVO;

/**
 * @author vison
 *
 */
public class StockAnalysisServiceImpl implements StockAnalysisService , InitializingBean{
	
	private final static Logger logger = LoggerFactory.getLogger(StockAnalysisServiceImpl.class);		
	
	@Resource
	private StockHistoryService stockHistoryService;
	
	@Resource
	private StockDailyLineDao stockDailyLineDao;

	@Resource
	private FilterProcessorManager filterProcessorManager;
	
	@Resource
	private StockInfoDao stockInfoDao;
	
	@Resource
	private StockCategoryDao stockCategoryDao;	
	
	private DecimalFormat decFormat = new DecimalFormat("##0.000");
	
	private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

	private Map<String , StockCategory> allDescMapCategoriesMap;
	
	private StockHelper inst = null;

	
	
	
	public StockHistoryService getStockHistoryService() {
		return stockHistoryService;
	}



	public void setStockHistoryService(StockHistoryService stockHistoryService) {
		this.stockHistoryService = stockHistoryService;
	}



	public StockDailyLineDao getStockDailyLineDao() {
		return stockDailyLineDao;
	}



	public void setStockDailyLineDao(StockDailyLineDao stockDailyLineDao) {
		this.stockDailyLineDao = stockDailyLineDao;
	}



	public FilterProcessorManager getFilterProcessorManager() {
		return filterProcessorManager;
	}



	public void setFilterProcessorManager(
			FilterProcessorManager filterProcessorManager) {
		this.filterProcessorManager = filterProcessorManager;
	}



	public StockInfoDao getStockInfoDao() {
		return stockInfoDao;
	}



	public void setStockInfoDao(StockInfoDao stockInfoDao) {
		this.stockInfoDao = stockInfoDao;
	}



	public StockCategoryDao getStockCategoryDao() {
		return stockCategoryDao;
	}



	public void setStockCategoryDao(StockCategoryDao stockCategoryDao) {
		this.stockCategoryDao = stockCategoryDao;
	}



	/* (non-Javadoc)
	 * @see org.vsg.stock.custcomp.service.StockAnalysisService#findHistoryPatternStocks(java.lang.String, java.util.Date, int)
	 */
	@Override
	public Collection<CloserPatternStock> findHistoryPatternStocks(
			String code, Date date, int cycle,int shapeCycle) throws ServiceException {
		// TODO Auto-generated method stub
		
		List<StockDailyLine> oneStockDailyLine = stockDailyLineDao.findStockLineByCycle(code, date, cycle);

		String pattern = stockHistoryService.getAbstractShapePattern( oneStockDailyLine , shapeCycle );

		Map<String , List<HistoryPatternStock>>  histPatternStockMap =  stockHistoryService.findHistoryPattern(pattern );

		List<CloserPatternStock> closerPatternStocks = filterProcessorManager.filterHandler( histPatternStockMap,code , oneStockDailyLine );
		
		return closerPatternStocks;
	}



	@Override
	public LinkageStockGroup findStockGroupByDate(Date date)
			throws ServiceException {
		// TODO Auto-generated method stub
		double lowestOverRatio = 5;
		List<StockDailyLine>  stkDailyList =  this.stockDailyLineDao.findStockLineByOverRatio(date, lowestOverRatio);
		StockDailyLine stkDailyLine = null;

		DecimalFormat decFormat = new DecimalFormat("##0.000");	
		
		StockDailyLine extStkDailyLineVo = null;
		
		Map<String ,Integer> cateDescCountMap = new HashMap<String, Integer>();
		Map<String ,List<StockDailyLine> > cateDescExtSDLMap = new HashMap<String ,List<StockDailyLine> >();
		
		for (int i = 0 ; i < stkDailyList.size() ; i++) {
			extStkDailyLineVo = stkDailyList.get(i);
			String stockCode = extStkDailyLineVo.getStockCode().toLowerCase();
			List<String> allDescByStkCode = stockCategoryDao.findDescriptionByStockCode( stockCode );
			String desc = null;
			for (Iterator<String> allDescBStkCodeIter = allDescByStkCode.iterator() ;  allDescBStkCodeIter.hasNext();) {
				desc = allDescBStkCodeIter.next();
				
				Integer countNum = cateDescCountMap.get( desc );
				List<StockDailyLine> extStkDailyLineVOList = null;
				if (countNum == null) {
					countNum = 1;
					extStkDailyLineVOList = new Vector<StockDailyLine>();
				} else {
					extStkDailyLineVOList = cateDescExtSDLMap.get(desc);
					++countNum;
				}
				cateDescCountMap.put(desc , countNum);
				extStkDailyLineVOList.add( extStkDailyLineVo );
				cateDescExtSDLMap.put( desc , extStkDailyLineVOList);
			}
		}
		
		LinkageStockGroup lsg = new LinkageStockGroup();
		lsg.setDate( date );
		
		List<LinkageStock> linkageStkList = new Vector<LinkageStock>();
		
		Set<Entry<String,Integer>> entries = cateDescCountMap.entrySet();
		Entry<String,Integer> entry = null;
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			
			List<StockDailyLine> extStkDailyLineVOList = cateDescExtSDLMap.get(key);


			StockDailyLine extStkDailyLineVO = null;
			double avgRatio = 0;
			double sumRatio = 0;
			for (Iterator<StockDailyLine> extStkDailyLineVOIter = extStkDailyLineVOList.iterator() ; extStkDailyLineVOIter.hasNext() ; ) {
				extStkDailyLineVO = extStkDailyLineVOIter.next();
				sumRatio+= extStkDailyLineVO.getYieldRate() * 100;
			}
			avgRatio = Double.parseDouble( decFormat.format(sumRatio / entry.getValue() ) );
			
			LinkageStock linkStock = new LinkageStock();
			linkStock.setCount( entry.getValue() );
			linkStock.setDescription(  key );
			linkStock.setAssoStocks( extStkDailyLineVOList );
			linkStock.setAvgRatio( avgRatio );
			linkageStkList.add( linkStock );
		}
		
		// ---- sort the list ---
		Collections.sort( linkageStkList ,new LinkageStockComparator());
		
		lsg.setLinkageStockList(linkageStkList);
		
		return lsg;
	}



	@Override
	public LinkageStockGroup findStockGroupByDate(Date date,
			int minimumTogetherNumber) throws ServiceException {
		// TODO Auto-generated method stub
		double lowestOverRatio = 5;
		List<StockDailyLine>  stkDailyList =  this.stockDailyLineDao.findStockLineByOverRatio(date, lowestOverRatio);
		StockDailyLine stkDailyLine = null;

		DecimalFormat decFormat = new DecimalFormat("##0.000");	
		
		StockDailyLine extStkDailyLineVo = null;
		
		Map<String ,Integer> cateDescCountMap = new HashMap<String, Integer>();
		Map<String ,List<StockDailyLine> > cateDescExtSDLMap = new HashMap<String ,List<StockDailyLine> >();
		
		for (int i = 0 ; i < stkDailyList.size() ; i++) {
			extStkDailyLineVo = stkDailyList.get(i);
			String stockCode = extStkDailyLineVo.getStockCode().toLowerCase();
			List<String> allDescByStkCode = stockCategoryDao.findDescriptionByStockCode( stockCode );
			String desc = null;
			for (Iterator<String> allDescBStkCodeIter = allDescByStkCode.iterator() ;  allDescBStkCodeIter.hasNext();) {
				desc = allDescBStkCodeIter.next();
				
				Integer countNum = cateDescCountMap.get( desc );
				List<StockDailyLine> extStkDailyLineVOList = null;
				if (countNum == null) {
					countNum = 1;
					extStkDailyLineVOList = new Vector<StockDailyLine>();
				} else {
					extStkDailyLineVOList = cateDescExtSDLMap.get(desc);
					++countNum;
				}
				cateDescCountMap.put(desc , countNum);
				extStkDailyLineVOList.add( extStkDailyLineVo );
				cateDescExtSDLMap.put( desc , extStkDailyLineVOList);
			}
		}
		
		LinkageStockGroup lsg = new LinkageStockGroup();
		lsg.setDate( date );
		
		List<LinkageStock> linkageStkList = new Vector<LinkageStock>();
		
		Set<Entry<String,Integer>> entries = cateDescCountMap.entrySet();
		Entry<String,Integer> entry = null;
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			
			if (minimumTogetherNumber > entry.getValue() ) {
				entriesIter.remove();
				continue;
			}
			
			List<StockDailyLine> extStkDailyLineVOList = cateDescExtSDLMap.get(key);

			StockDailyLine extStkDailyLineVO = null;
			double avgRatio = 0;
			double sumRatio = 0;
			for (Iterator<StockDailyLine> extStkDailyLineVOIter = extStkDailyLineVOList.iterator() ; extStkDailyLineVOIter.hasNext() ; ) {
				extStkDailyLineVO = extStkDailyLineVOIter.next();
				sumRatio+= extStkDailyLineVO.getYieldRate() * 100;
			}
			avgRatio = Double.parseDouble( decFormat.format(sumRatio / entry.getValue() ) );
			
			LinkageStock linkStock = new LinkageStock();
			linkStock.setCount( entry.getValue() );
			linkStock.setDescription(  key );
			linkStock.setAssoStocks( extStkDailyLineVOList );
			linkStock.setAvgRatio( avgRatio );
			linkageStkList.add( linkStock );
		}
		
		// ---- sort the list ---
		Collections.sort( linkageStkList ,new LinkageStockComparator());
		
		lsg.setLinkageStockList(linkageStkList);
		
		return lsg;
	}

	
	
	@Override
	public List<LinkageStockGroup> findStockGroupListInPeriod(Date fromDate,
			Date toDate, int minimumTogetherNumber) throws ServiceException {
		// TODO Auto-generated method stub
		double lowestOverRatio = 5;
		
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);
		tmpCale.add(Calendar.DATE, -1);
		

		// --- fix the long holiday
		LinkageStockGroup linkageStkGroup = null;
		LinkageStock linkageStk = null;
		
		List<LinkageStockGroup> groupList = new Vector<LinkageStockGroup>();
		
		Map<String , StockCategory> descMapCategoriesMap = getAllDescMapCategoriesMap();
		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		
		while (toDate.compareTo(tmpCale.getTime()) >  0) {
			
			tmpCale.add(Calendar.DATE, 1);
			if (tmpCale.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY 
					|| tmpCale.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ) {
				continue;
			}
			tmpDate = tmpCale.getTime();
			// -------- other method handle ---
			List<StockDailyLine>  stkDailyList =  this.stockDailyLineDao.findStockLineByOverRatio(tmpDate, lowestOverRatio);
			// --- defined category mapping ---
			Map<String ,Integer> cateDescCountMap = new HashMap<String, Integer>();
			Map<String ,List<StockDailyLine> > cateDescSDLMap = new HashMap<String ,List<StockDailyLine> >();


			// --- map the description and list ---
			StockDailyLine stkDL = null;
			for (int i = 0 ; i < stkDailyList.size() ; i++) {
				stkDL = stkDailyList.get(i);
				String stockCode = stkDL.getStockCode().toLowerCase();
				List<String> allDescByStkCode = stockCategoryDao.findDescriptionByStockCode( stockCode );
				String desc = null;
				List<StockDailyLine> stkDailyLineList  = null;				
				for (Iterator<String> allDescBStkCodeIter = allDescByStkCode.iterator() ;  allDescBStkCodeIter.hasNext();) {
					desc = allDescBStkCodeIter.next();
					Integer countNum = cateDescCountMap.get( desc );
					

					if (countNum == null) {
						countNum = 1;
						stkDailyLineList = new Vector<StockDailyLine>();
					} else {
						++countNum;
						stkDailyLineList = cateDescSDLMap.get( desc );
					}
					if (!stkDailyLineList.contains( stkDL )) {
						stkDailyLineList.add( stkDL );
						cateDescSDLMap.put( desc , stkDailyLineList);
					}
					cateDescCountMap.put(desc , countNum);
				}
			}

			List<LinkageStock> linkageStkList = new Vector<LinkageStock>();
			Set<Entry<String,Integer>> entries = cateDescCountMap.entrySet();
			Entry<String,Integer> entry = null;

			for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
				entry = entriesIter.next();
				String key = entry.getKey();
				
				if (minimumTogetherNumber > entry.getValue() ) {
					entriesIter.remove();
					continue;
				}
				
				List<StockDailyLine> extStkDailyLineVOList = cateDescSDLMap.get(key);

				StockDailyLine extStkDailyLineVO = null;
				double avgRatio = 0;
				double sumRatio = 0;
				for (Iterator<StockDailyLine> extStkDailyLineVOIter = extStkDailyLineVOList.iterator() ; extStkDailyLineVOIter.hasNext() ; ) {
					extStkDailyLineVO = extStkDailyLineVOIter.next();
					sumRatio+= extStkDailyLineVO.getYieldRate() * 100;
				}
				avgRatio = Double.parseDouble( decFormat.format(sumRatio / entry.getValue() ) );
				
				Integer count = descMapCounter.get( key );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}
				
				linkageStk = new LinkageStock();
				linkageStk.setStockCategory( descMapCategoriesMap.get(key) );
				linkageStk.setDescription( key );
				linkageStk.setAssoStocks( cateDescSDLMap.get(key) );
				linkageStk.setAvgRatio( avgRatio );
				linkageStk.setCount( entry.getValue() );
				linkageStkList.add( linkageStk );

				descMapCounter.put( key , count);				
			}

			Collections.sort( linkageStkList ,new LinkageStockComparator());
			
			linkageStkGroup = new LinkageStockGroup();
			linkageStkGroup.setDate( tmpDate) ;
			linkageStkGroup.setLinkageStockList( linkageStkList );
			

			groupList.add(linkageStkGroup);

		}
		


		
		return groupList;
	}



	private Map<String , StockCategory> getAllDescMapCategoriesMap() {
		// --- get the all category map ---
		if (allDescMapCategoriesMap == null) {
			Map<String , StockCategory> descMapCategoriesMap = new HashMap<String, StockCategory>();
			List<StockCategory> allStockCategory = stockCategoryDao.findAllCategory();
			StockCategory cate = null;
			for (Iterator<StockCategory> scIter = allStockCategory.iterator() ; scIter.hasNext() ; ) {
				cate = scIter.next();
				descMapCategoriesMap.put( cate.getDescription() , cate);
			}
			this.allDescMapCategoriesMap = descMapCategoriesMap;
		} 
		return this.allDescMapCategoriesMap;
	}


	@Override
	public List<LinkageStockGroupCounterVO> findStockGroupCounterInPeriod(
			Date fromDate, Date toDate, int minimumTogetherNumber)
			throws ServiceException {
		// TODO Auto-generated method stub
		double lowestOverRatio = 5;
		
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);
		tmpCale.add(Calendar.DATE, -1);
		

		// --- fix the long holiday
		LinkageStockGroup linkageStkGroup = null;
		LinkageStock linkageStk = null;
		
		
		Map<String , StockCategory> descMapCategoriesMap = getAllDescMapCategoriesMap();
		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		
		while (toDate.compareTo(tmpCale.getTime()) >  0) {
			
			tmpCale.add(Calendar.DATE, 1);
			if (tmpCale.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY 
					|| tmpCale.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY ) {
				continue;
			}
			tmpDate = tmpCale.getTime();
			// -------- other method handle ---
			List<StockDailyLine>  stkDailyList =  this.stockDailyLineDao.findStockLineByOverRatio(tmpDate, lowestOverRatio);
			
			Map<String ,Integer> cateDescCountMap = new HashMap<String, Integer>();
			Map<String ,List<StockDailyLine> > cateDescSDLMap = new HashMap<String ,List<StockDailyLine> >();
			
			StockDailyLine stkDL = null;
			for (int i = 0 ; i < stkDailyList.size() ; i++) {
				stkDL = stkDailyList.get(i);
				String stockCode = stkDL.getStockCode().toLowerCase();
				List<String> allDescByStkCode = stockCategoryDao.findDescriptionByStockCode( stockCode );
				String desc = null;
				List<StockDailyLine> stkDailyLineList  = null;				
				for (Iterator<String> allDescBStkCodeIter = allDescByStkCode.iterator() ;  allDescBStkCodeIter.hasNext();) {
					desc = allDescBStkCodeIter.next();
					Integer countNum = cateDescCountMap.get( desc );
					

					if (countNum == null) {
						countNum = 1;
						stkDailyLineList = new Vector<StockDailyLine>();
					} else {
						++countNum;
						stkDailyLineList = cateDescSDLMap.get( desc );
					}
					if (!stkDailyLineList.contains( stkDL )) {
						stkDailyLineList.add( stkDL );
						cateDescSDLMap.put( desc , stkDailyLineList);
					}
					cateDescCountMap.put(desc , countNum);
				}
			}

			Set<Entry<String,Integer>> entries = cateDescCountMap.entrySet();
			Entry<String,Integer> entry = null;
			for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
				entry = entriesIter.next();
				String key = entry.getKey();
				
				if (minimumTogetherNumber > entry.getValue() ) {
					entriesIter.remove();
					continue;
				}
				
				List<StockDailyLine> extStkDailyLineVOList = cateDescSDLMap.get(key);

				StockDailyLine extStkDailyLineVO = null;
				double avgRatio = 0;
				double sumRatio = 0;
				for (Iterator<StockDailyLine> extStkDailyLineVOIter = extStkDailyLineVOList.iterator() ; extStkDailyLineVOIter.hasNext() ; ) {
					extStkDailyLineVO = extStkDailyLineVOIter.next();
					sumRatio+= extStkDailyLineVO.getYieldRate() * 100;
				}
				avgRatio = Double.parseDouble( decFormat.format(sumRatio / entry.getValue() ) );
				
				Integer count = descMapCounter.get( key );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}

				descMapCounter.put( key , count);				
			}

		
		}

		Set<Entry<String,Integer>> entries = descMapCounter.entrySet();
		Entry<String,Integer> entry = null;
		LinkageStockGroupCounterVO counterVO = null;
		List<LinkageStockGroupCounterVO> counterVOList = new Vector<LinkageStockGroupCounterVO>();
		
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			int value = entry.getValue();
			counterVO = new LinkageStockGroupCounterVO();
			counterVO.setCount( value );
			counterVO.setStkCategory( descMapCategoriesMap.get(key) );
			
			
			counterVOList.add( counterVO );
		}		
		
		// ---- sort the list ---
		Collections.sort( counterVOList ,new CounterSortComparator());
		
		return counterVOList;
	}

	@Override
	public List<LinkageStockGroupCounterView> findFrequencyLinkageStockGroup(
			Date fromDate, int cycle) throws ServiceException {
		// TODO Auto-generated method stub
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		Map<String, LinkageStocksItemVO> descMapItemVO = new HashMap<String , LinkageStocksItemVO>();
		
		LinkageStocksItemVO itemVO = null;
		
		while (cycle > 0) {
			
			if (!inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);					
				continue;
			}			
			
			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());
			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				
				Integer count = descMapCounter.get( itemVO.getDescription() );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}				
				descMapCounter.put( itemVO.getDescription() , count);
				
				if (descMapItemVO.get( itemVO.getDescription() ) == null) {
					descMapItemVO.put(itemVO.getDescription() , itemVO);
				}
				
				itemIter.remove();
			}

			tmpCale.add(Calendar.DATE, -1);		
			--cycle;
		}
		
		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		Set<Entry<String,Integer>> entries = descMapCounter.entrySet();
		Entry<String,Integer> entry = null;
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			int value = entry.getValue();
			
			view = new LinkageStockGroupCounterView();
			view.setDescription( entry.getKey() );
			itemVO = descMapItemVO.get( entry.getKey() );
			
			view.setType( convertTypeName( itemVO.getType() ) );
			view.setId( itemVO.getCategoryId() );
			view.setCount( value );
			
			viewList.add( view ); 
		}			
		Collections.sort( viewList ,new CounterSortComparator());				
		
		return viewList;
	}



	@Override
	public List<LinkageStockGroupCounterView> findLinkageStockGroupCounterViewInFrontOf(
			Date fromDate, int cycle, String type) throws ServiceException {
		// TODO Auto-generated method stub
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		Map<String , LinkageStocksItemVO> descMapItem = new HashMap<String , LinkageStocksItemVO>();
		
		LinkageStocksItemVO itemVO = null;
		while (cycle > 0) {

			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}			

			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());

			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				if (!itemVO.getType().equals( type )) {
					continue;
				}
				
				Integer count = descMapCounter.get( itemVO.getDescription() );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}				
				descMapCounter.put( itemVO.getDescription() , count);
				descMapItem.put( itemVO.getDescription() , itemVO);
				itemIter.remove();
			}
			

			tmpCale.add(Calendar.DATE, -1);		
			--cycle;
		}
		


		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		Set<Entry<String,Integer>> entries = descMapCounter.entrySet();
		Entry<String,Integer> entry = null;
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			int value = entry.getValue();
			
			view = new LinkageStockGroupCounterView();
			view.setDescription( entry.getKey() );
			view.setType( convertTypeName(type) );
			view.setId( descMapItem.get(  entry.getKey() ).getCategoryId() );
			view.setCount( value );
			
			viewList.add( view ); 
		}			
		Collections.sort( viewList ,new CounterSortComparator());				
		
		return viewList;
	}
	
	private String convertTypeName(String type ) {
		String cateName = null;
		
		if (StockCategory.CONCEPT.equalsIgnoreCase( type )) {
			cateName = "概 念";
		}
		else if ( StockCategory.PLATE.equalsIgnoreCase( type ) ) {
			cateName = "板 块";
		}
		else if ( StockCategory.TRADES.equalsIgnoreCase( type ) ) {
			cateName = "行 业";
		}
		else if ( StockCategory.SAME_STOCKHOLDER.equalsIgnoreCase( type ) ) {
			cateName ="同一主力/机构";
		}		
		else if ( StockCategory.STANDARD_TRADES.equalsIgnoreCase( type ) ) {
			cateName = "证监会行业";
		}		
		else if ( StockCategory.ZONE.equalsIgnoreCase( type ) ) {
			cateName = "区 域";
		}
		else if ( StockCategory.OTHERS.equalsIgnoreCase( type ) ) {
			cateName = "其 他";
		}		
		
		return cateName;
	}



	@Override
	public List<LinkageStockGroupCounterView> findLinkageStockGroupCounterViewInFrontOf(
			Date fromDate, int cycle, int notInFrontOfCycle, String type)
			throws ServiceException {
		// TODO Auto-generated method stub
		
		
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		
		LinkageStocksItemVO itemVO = null;

		while (cycle > 0) {
			
			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}			

			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());
			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				
				if (!itemVO.getType().equals( type )) {
					continue;
				}
				
				Integer count = descMapCounter.get( itemVO.getDescription() );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}				
				descMapCounter.put( itemVO.getDescription() , count);
				
				itemIter.remove();
			}
			

			tmpCale.add(Calendar.DATE, -1);		
			--cycle;
		}

		// --- get the not exist count ---
		Set<String> descSet = new HashSet<String>();
		while (notInFrontOfCycle > 0) {
			
			if (!inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}			

			List<String>  descList = this.stockHistoryService.findLinkageStocksDescByDate(tmpCale.getTime());
			descSet.addAll( descList );

			tmpCale.add(Calendar.DATE, -1);		
			--notInFrontOfCycle;
		}

		Set<Entry<String,Integer>> entries = descMapCounter.entrySet();
		Entry<String,Integer> entry = null;
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			if (descSet.contains(key)) {
				entriesIter.remove();
			}
		}
		
		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		for (Iterator<Entry<String,Integer>> entriesIter = entries.iterator() ; entriesIter.hasNext(); ) {
			entry = entriesIter.next();
			String key = entry.getKey();
			int value = entry.getValue();

			StockCategory stkCate = this.allDescMapCategoriesMap.get(entry.getKey() );			
			
			view = new LinkageStockGroupCounterView();
			view.setDescription( entry.getKey() );
			view.setType( convertTypeName(type) );
			view.setCount( value );
			view.setId( Integer.toString( stkCate.getId() ) );
			
			viewList.add( view ); 
		}			
		Collections.sort( viewList ,new CounterSortComparator());				
		
		return viewList;
	}


	
	

	@Override
	public List<LinkageStockGroupCounterView> findAllLinkageStockGroupCounterViewInFrontOf(
			Date fromDate, int cycle, int chartsCycle) throws ServiceException {
		// TODO Auto-generated method stub
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		
		int diffCycle = cycle - chartsCycle;
		
		Set<String> chartsCateDescSet = new HashSet<String>();
		Set<String> diffCateDescSet = new HashSet<String>();

		LinkageStocksItemVO itemVO = null;
		// --- convert the cycle defined ---
		while (chartsCycle > 0) {
			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}
			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());

			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				chartsCateDescSet.add( itemVO.getDescription() );

				Integer count = descMapCounter.get( itemVO.getDescription() );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}					
				descMapCounter.put( itemVO.getDescription() , count);				
				itemIter.remove();
			}
			tmpCale.add(Calendar.DATE, -1);		
			--chartsCycle;
		}

		// --- get the not exist count ---
		Set<String> descSet = new HashSet<String>();
		while (diffCycle > 0) {
			if (!inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}			
			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());


			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				diffCateDescSet.add( itemVO.getDescription() );
				itemIter.remove();
			}

			tmpCale.add(Calendar.DATE, -1);		
			--diffCycle;
		}
		
		// --- debug defined check defined list ---
		if ( logger.isDebugEnabled() ) {
			logger.debug("Category Description in chartsCycle , total : " + chartsCateDescSet.size());
			for (String desc : chartsCateDescSet) {
				logger.debug(desc);
			}
			logger.info("Category Description in discrepancy cycle , total : " + diffCateDescSet.size());
			for (String desc : diffCateDescSet) {
				logger.info(desc);
			}
		}
		
		// --- remove the contain value ---
		String cateDesc = null;
		for (Iterator<String> descDiffCateIter = chartsCateDescSet.iterator() ; descDiffCateIter.hasNext(); ) {
			cateDesc = descDiffCateIter.next();
			
			if (diffCateDescSet.contains( cateDesc )) {
				descDiffCateIter.remove();
			}
		}

		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		for (Iterator<String> entriesIter = chartsCateDescSet.iterator() ; entriesIter.hasNext(); ) {
			cateDesc = entriesIter.next();
			
			StockCategory stkCate = this.allDescMapCategoriesMap.get(cateDesc);
			
			view = new LinkageStockGroupCounterView();
			
			view.setDescription( cateDesc );
			view.setType( convertTypeName( stkCate.getType() ) );
			view.setCount( descMapCounter.get(cateDesc) );
			view.setId( Integer.toString( stkCate.getId() ) );			
			viewList.add( view ); 
			
		}
		
		Collections.sort( viewList ,new CounterSortComparator());				
		return viewList;

	}



	@Override
	public List<LinkageStockGroupCounterView> findAllLinkageStockGroupCounterViewInFrontOf(
			Date fromDate) throws ServiceException {
		// TODO Auto-generated method stub
		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		
		
		Set<String> chartsCateDescSet = new HashSet<String>();
		Set<String> diffCateDescSet = new HashSet<String>();

		LinkageStocksItemVO itemVO = null;
		// --- convert the cycle defined ---
		List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());

		for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
			itemVO = itemIter.next();
			chartsCateDescSet.add( itemVO.getDescription() );

			Integer count = descMapCounter.get( itemVO.getDescription() );
			if (count == null) {
				count = 1;
			}  else {
				++count;
			}					
			descMapCounter.put( itemVO.getDescription() , count);				
			itemIter.remove();
		}

		// --- debug defined check defined list ---
		if ( logger.isDebugEnabled() ) {
			logger.debug("Category Description in chartsCycle , total : " + chartsCateDescSet.size());
			for (String desc : chartsCateDescSet) {
				logger.debug(desc);
			}
			logger.info("Category Description in discrepancy cycle , total : " + diffCateDescSet.size());
			for (String desc : diffCateDescSet) {
				logger.info(desc);
			}
		}
		
		// --- remove the contain value ---
		String cateDesc = null;

		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		for (Iterator<String> entriesIter = chartsCateDescSet.iterator() ; entriesIter.hasNext(); ) {
			cateDesc = entriesIter.next();
			
			StockCategory stkCate = this.allDescMapCategoriesMap.get(cateDesc);
			
			view = new LinkageStockGroupCounterView();
			
			view.setDescription( cateDesc );
			view.setType( convertTypeName( stkCate.getType() ) );
			view.setCount( descMapCounter.get(cateDesc) );
			view.setId( Integer.toString( stkCate.getId() ) );
			viewList.add( view ); 
			
		}
		
		//Collections.sort( viewList ,new CounterSortComparator());				
		return viewList;
	}



	
	@Override
	public List<LinkageCateShownSequenceVO> findCateShownSequenceByCategoryDesc(
			Date fromDate, int cycle, String cateDesc) throws ServiceException {
		// TODO Auto-generated method stub
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);
		
		List<LinkageCateShownSequenceVO> sequenceList = new Vector<LinkageCateShownSequenceVO>();
		
		double rate = 0;
		int showId = 0;
		boolean exist = false;
		Date tmpDate = null;

		while (cycle > 0) {
			
			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}
			LinkageStocksItemVO itemVo = null;
			List<LinkageStocksItemVO> linkageStkItemList = stockHistoryService.findLinkageStocksItemByDate( tmpCale.getTime() );
			for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
				itemVo = linkageStkItemIter.next();
				if ( itemVo.getDescription().equals( cateDesc ) ) {
					tmpDate = tmpCale.getTime();
					rate = itemVo.getAvgRatio();
					exist = true;
					break;
				}
			}
			
			if (exist) {
				LinkageCateShownSequenceVO vo = new LinkageCateShownSequenceVO();
				vo.setShowId( ++showId );
				vo.setCateDate( tmpDate );
				vo.setCateDesc( cateDesc );
				vo.setRate( rate );
				sequenceList.add(vo);
				exist = false;
			} 
			tmpCale.add(Calendar.DATE, -1);		
			--cycle;
		}

		
		// --- get the last shown date ---
		boolean getLastDate = true;
		short maxLastDateCycle = 120; // set standard value
		short tmpLastDateCycleCount = 0;
		while (getLastDate) {
			++tmpLastDateCycleCount;
			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}
			LinkageStocksItemVO itemVo = null;
			List<LinkageStocksItemVO> linkageStkItemList = stockHistoryService.findLinkageStocksItemByDate( tmpCale.getTime() );
			for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
				itemVo = linkageStkItemIter.next();
				if ( itemVo.getDescription().equals( cateDesc ) ) {
					tmpDate = tmpCale.getTime();
					getLastDate = false;
					break;
				}
			}
			if (tmpLastDateCycleCount > maxLastDateCycle) {
				tmpDate = tmpCale.getTime();
				getLastDate = false;
			}

			tmpCale.add(Calendar.DATE, -1);		
		}
		
		
		// --- count the value ---
		int interval = 0;
		LinkageCateShownSequenceVO sequenceVo = null;
		Date lastDate = tmpDate;
		
		for (int i = sequenceList.size() - 1 ; i >= 0 ; i--) {
			sequenceVo = sequenceList.get(i);
			
			tmpCale.setTime( sequenceVo.getCateDate() );
			while (tmpCale.getTime().after( lastDate) ) {
				
				tmpDate = tmpCale.getTime();
				tmpCale.add(Calendar.DATE, -1);	
				if (!this.inst.isTradingDate( tmpDate ) ) {
					continue;
				}
				++interval;
			}
			
			sequenceVo.setInterval( interval );
			// --- reset value --- 
			interval = 0;
			lastDate = sequenceVo.getCateDate();
		}

		
		return sequenceList;
	}



	@Override
	public List<LinkageCateStockVO> findCateStockByCategoryDesc(Date fromDate,
			int cycle, String cateDesc) throws ServiceException {
		// TODO Auto-generated method stub
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);
		
		Set<String> stkCodeSet = new HashSet<String>();
		Map<String,List<String>> stkCodeCategoryMap = new HashMap<String,List<String>>();
		Map<String,List<Date>> stkCodeShownDateMap = new HashMap<String,List<Date>>();
		
		
		// --- add the stkcode to set ---
		LinkageStocksItemVO itemVo = null;
		List<LinkageStocksItemVO> linkageStkItemList = stockHistoryService.findLinkageStocksItemByDate( tmpCale.getTime() );
		for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
			itemVo = linkageStkItemIter.next();
			if ( itemVo.getDescription().equals( cateDesc ) ) {
				String[] stkCodes = itemVo.getStockCodes();
				for (String code : stkCodes) {
					stkCodeSet.add(code);
					stkCodeCategoryMap.put(code, new Vector<String>() );
					stkCodeShownDateMap.put(code, new Vector<Date>() );
					
				}
			}
		}

		
		// --- set the category map ---
		for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
			itemVo = linkageStkItemIter.next();
			String[] stkCodes = itemVo.getStockCodes();
			for (int i = 0 ; i < stkCodes.length ; i++) {
				if (stkCodeSet.contains( stkCodes[i] )) {
					List<String> cateList = stkCodeCategoryMap.get(stkCodes[i]);
					if (!cateList.contains( itemVo.getDescription() )) {
						cateList.add( itemVo.getDescription() );
					}
				}
			}
		}
		
		
		// --- set the dateMap ---
		while (cycle > 0) {
			if (!this.inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);	
				continue;
			}
			linkageStkItemList = stockHistoryService.findLinkageStocksItemByDate( tmpCale.getTime() );
			for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
				itemVo = linkageStkItemIter.next();
				if ( itemVo.getDescription().equals( cateDesc ) ) {
					String[] stkCodes = itemVo.getStockCodes();
					for (int i = 0 ; i < stkCodes.length ; i++) {
						if (stkCodeSet.contains( stkCodes[i] )) {
							List<Date> cateList = stkCodeShownDateMap.get(stkCodes[i]);
							cateList.add( tmpCale.getTime() );
						}
					}
				}
			}			
			tmpCale.add(Calendar.DATE, -1);		
			--cycle;
		}
		
		
		List<LinkageCateStockVO> stkList = new Vector<LinkageCateStockVO>();
		
		// --- set the handle object ---
		String stkCode = null;
		StockDailyLine sdl = null;
		LinkageCateStockVO stockVo = null;
		StockInfo stkInfo = null;
		for (Iterator<String> stkCodeIter = stkCodeSet.iterator() ; stkCodeIter.hasNext(); ) {
			stkCode = stkCodeIter.next();
			sdl = stockDailyLineDao.getDailyLineFromDate(stkCode, fromDate);
			stkInfo = (StockInfo)stockInfoDao.load(StockInfo.class, stkCode);

			stockVo = new LinkageCateStockVO();
			stockVo.setStockCode( stkCode );
			stockVo.setRate( Double.parseDouble( decFormat.format( sdl.getYieldRate()) ) );
			stockVo.setStockName( stkInfo.getName() );
			
			// --- get date handle ---
			List<Date> dateList = stkCodeShownDateMap.get(stkCode);
			Date date;
			StringBuilder dateStr = new StringBuilder();
			for (Iterator<Date> dateIter = dateList.iterator(); dateIter.hasNext();) {
				date = dateIter.next();
				
				dateStr.append( dateFormat.format(date) );
				
				if ( dateIter.hasNext() ) {
					dateStr.append(" , ");
				}
			}
			stockVo.setAssemblyDates( dateStr.toString() );

			List<String> cateList = stkCodeCategoryMap.get(stkCode);
			StringBuilder cateStr = new StringBuilder();
			String cate;
			for (Iterator<String> cateIter = cateList.iterator(); cateIter.hasNext();) {
				cate = cateIter.next();
				
				cateStr.append( cate );
				
				if ( cateIter.hasNext() ) {
					cateStr.append(" , ");
				}
			}
			stockVo.setAssemblyCates( cateStr.toString() );
			
			stkList.add( stockVo );
			
		}
		
		Collections.sort( stkList ,new LinkageCateStockSortComparator());	
		
		return stkList;
	}

	


	@Override
	public List<LinkageStockGroupCounterView> findFrequencyLinkageStockGroup(
			Date fromDate, int cycle, int recent) throws ServiceException {
		// TODO Auto-generated method stub

		Date tmpDate = null;
		Calendar tmpCale = Calendar.getInstance();
		tmpCale.setTime(fromDate);

		Map<String , Integer> descMapCounter = new HashMap<String , Integer>();
		Map<String, LinkageStocksItemVO> descMapItemVO = new HashMap<String , LinkageStocksItemVO>();
		
		LinkageStocksItemVO itemVO = null;
		
		int diff = cycle - recent;
		
		
		Set<String> existDesc = new HashSet<String>();
		
		while (recent > 0) {
			
			if (!inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);					
				continue;
			}			
			
			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());
			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				
				Integer count = descMapCounter.get( itemVO.getDescription() );
				if (count == null) {
					count = 1;
				}  else {
					++count;
				}				
				descMapCounter.put( itemVO.getDescription() , count);
				
				if (descMapItemVO.get( itemVO.getDescription() ) == null) {
					descMapItemVO.put(itemVO.getDescription() , itemVO);
				}
				existDesc.add(  itemVO.getDescription() );
				itemIter.remove();
			}

			tmpCale.add(Calendar.DATE, -1);		
			--recent;
		}

		while (diff > 0) {
			
			if (!inst.isTradingDate( tmpCale ) ) {
				tmpCale.add(Calendar.DATE, -1);					
				continue;
			}			
			
			List<LinkageStocksItemVO>  itemList = this.stockHistoryService.findLinkageStocksItemByDate(tmpCale.getTime());
			for (Iterator<LinkageStocksItemVO> itemIter = itemList.iterator() ; itemIter.hasNext(); ) {
				itemVO = itemIter.next();
				
				if (existDesc.contains( itemVO.getDescription() )) {
					existDesc.remove( itemVO.getDescription() );
				}
				itemIter.remove();
			}

			tmpCale.add(Calendar.DATE, -1);		
			--diff;
		}
		
		
		
		LinkageStockGroupCounterView view = null;
		List<LinkageStockGroupCounterView> viewList = new Vector<LinkageStockGroupCounterView>();
		Set<Entry<String,Integer>> entries = descMapCounter.entrySet();
		Entry<String,Integer> entry = null;
		
		String cateDesc = null;
		for (Iterator<String> entriesIter = existDesc.iterator() ; entriesIter.hasNext(); ) {
			cateDesc = entriesIter.next();
			
			StockCategory stkCate = this.allDescMapCategoriesMap.get(cateDesc);
			
			view = new LinkageStockGroupCounterView();
			
			view.setDescription( cateDesc );
			view.setType( convertTypeName( stkCate.getType() ) );
			view.setCount( descMapCounter.get(cateDesc) );
			view.setId(  Integer.toString( stkCate.getId() ) );
			
			viewList.add( view ); 
			
		}		
		
		Collections.sort( viewList ,new CounterSortComparator());				
		
		return viewList;
		
	}



	@Override
	public void saveAttentionBlock(List<AttentionBlock> orgList,
			AttentionBlock ab) throws ServiceException {
		// TODO Auto-generated method stub
		AttentionBlock orgAttenBlock = null;
		for (Iterator<AttentionBlock> orgIter = orgList.iterator() ; orgIter.hasNext() ; ) {
			orgAttenBlock = orgIter.next();
			
			if (orgAttenBlock.getId().equals( ab.getId() ) ) {
				// --- check and replase the object
				orgIter.remove();
				break;
			}
		}
		orgList.add(ab);

		
	}
	



	@Override
	public List<LinkageCateStockVO> analyseStocksFromAttentionBlock(
			List<AttentionBlock> assoAttentionBlock) throws ServiceException {
		// TODO Auto-generated method stub
		

		Calendar tmpCale = Calendar.getInstance();
		
		Set<String> existStkCode = new HashSet<String>();
		Map<String,List<String>> stkCodeCategoryMap = new HashMap<String,List<String>>();
		Map<String,Date> stkCodeShownDateMap = new HashMap<String,Date>();		
		
		AttentionBlock attentionBlock = null;
		for (Iterator<AttentionBlock> attenBlockIter = assoAttentionBlock.iterator() ; attenBlockIter.hasNext(); ) {
			attentionBlock = attenBlockIter.next();
			
			int cycle = attentionBlock.getCycle();
			tmpCale.setTime( attentionBlock.getStartDate() );
			// --- get the ref date and cycle ---
			while (cycle > 0) {
				if (!this.inst.isTradingDate( tmpCale ) ) {
					tmpCale.add(Calendar.DATE, -1);	
					continue;
				}
				List<LinkageStocksItemVO> linkageStkItemList = stockHistoryService.findLinkageStocksItemByDate( tmpCale.getTime() );
				LinkageStocksItemVO itemVo = null;
				for (Iterator<LinkageStocksItemVO> linkageStkItemIter = linkageStkItemList.iterator(); linkageStkItemIter.hasNext(); ) {
					itemVo = linkageStkItemIter.next();
					
					if ( itemVo.getCategoryId().equals( attentionBlock.getId()) )  {
						List<String> assoStkList = Arrays.asList( itemVo.getStockCodes() );
						for (Iterator<String> assoStkCodeIter = assoStkList.iterator() ; assoStkCodeIter.hasNext(); ) {
							String stkCode = assoStkCodeIter.next();
							
							// --- create new not map stkCode ---
							if (!existStkCode.contains( stkCode) ) {
								
								List<String> assoCateList = new Vector<String>();
								assoCateList.add( itemVo.getDescription() ); 
								stkCodeCategoryMap.put(stkCode, assoCateList);
								
								stkCodeShownDateMap.put(stkCode, tmpCale.getTime() );
								existStkCode.add( stkCode );
								
							} else {
								// --- add new association ---
								List<String> assoCateList = stkCodeCategoryMap.get( stkCode );
								if (!assoCateList.contains( itemVo.getDescription() ) ) {
									assoCateList.add( itemVo.getDescription() );
								}
							}
						}
						
					}
				}			
				tmpCale.add(Calendar.DATE, -1);		
				--cycle;
			}			
		}
		
		String stkCode = null;
		StockDailyLine sdl = null;
		LinkageCateStockVO stockVo = null;
		StockInfo stkInfo = null;
		
		List<LinkageCateStockVO>  list = new LinkedList<LinkageCateStockVO>();

		for (Iterator<String> entriesIter = existStkCode.iterator() ; entriesIter.hasNext(); ) {
			stkCode = entriesIter.next();
			
			Date shownDate = stkCodeShownDateMap.get( stkCode );
			sdl = stockDailyLineDao.getDailyLineFromDate(stkCode, shownDate);			
			stkInfo = (StockInfo)stockInfoDao.load(StockInfo.class, stkCode);			
			List<String> cateList = stkCodeCategoryMap.get(stkCode);
			StringBuilder cateStr = new StringBuilder();
			String cate;
			for (Iterator<String> cateIter = cateList.iterator(); cateIter.hasNext();) {
				cate = cateIter.next();
				
				cateStr.append( cate );
				
				if ( cateIter.hasNext() ) {
					cateStr.append(" , ");
				}
			}
			
			stockVo = new LinkageCateStockVO();
			stockVo.setStockCode( stkCode );
			stockVo.setRate( Double.parseDouble( decFormat.format( sdl.getYieldRate()) ) );
			stockVo.setStockName( stkInfo.getName() );
			
			stockVo.setLastShownDate( shownDate);
			stockVo.setAssemblyCates( cateStr.toString() );

			list.add( stockVo );

		}			
		
		Collections.sort( list ,new BlockCateStockViewSortComparator());	
		
		return list;
	}



	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		this.allDescMapCategoriesMap = getAllDescMapCategoriesMap();
		
		this.inst = StockHelper.getInstance();
	}

	
	
	
}
